package com.sky.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable;
import org.springframework.cache.annotation.CachePut;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @program: sky-take-out
 * @description:
 * @author: 酷炫焦少
 * @create: 2024-11-16 15:47
 **/
@Service
@Slf4j
public class DishServiceImpl implements DishService {

    @Resource
    private DishMapper dishMapper;

    @Resource
    private DishFlavorMapper dishFlavorMapper;

    @Resource
    private SetmealDishMapper setmealDishMapper;

    @Resource
    private RedisTemplate<Object, Object> redisTemplate;

    private Result<String> dishResult(DishDTO dishDTO) {
        if (Objects.isNull(dishDTO)) {
            return Result.error("添加菜品失败");
        }
        if (StrUtil.isBlank(dishDTO.getName())) {
            return Result.error("菜品名称不能为空");
        }
        BigDecimal price = dishDTO.getPrice();
        if (Objects.isNull(price) || price.scale() > 2) {
            return Result.error("菜品价格输入错误，请重新输入");
        }
        if (dishDTO.getDescription().length() > 200) {
            return Result.error("菜品描述超过200字");
        }
        return null;
    }

    @Override
    @Transactional
    public Result<String> addDish(DishDTO dishDTO) {
        Result<String> r = dishResult(dishDTO);
        if (!Objects.isNull(r)) {
            return r;
        }
        Dish dish = BeanUtil.copyProperties(dishDTO, Dish.class);
        int result = dishMapper.saveDish(dish);
        if (result < 1) {
            return Result.error("添加菜品失败");
        }
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if (CollectionUtil.isNotEmpty(flavors)) {
            int row = dishFlavorMapper.saveDishFlavors(dish.getId(), flavors);
            if (row < 1) {
                return Result.error("添加菜品失败");
            }
        }
        dish.setStatus(StatusConstant.ENABLE);
        redisTemplate.delete("dish:" + dish.getCategoryId());
        return Result.success("添加菜品成功！");
    }

    @Override
    public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO) {
        PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());
        Dish dish = BeanUtil.copyProperties(dishPageQueryDTO, Dish.class);
        List<DishVO> dishes = dishMapper.list(dish);
        PageInfo<DishVO> pageInfo = new PageInfo<>(dishes);
        return Result.success(new PageResult(pageInfo.getTotal(), pageInfo.getList()));
    }

    @Override
    public Result<String> deleteDish(List<Long> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            return Result.error("请选择你要删除的菜品");
        }
        int count = dishMapper.queryCountByStatus(StatusConstant.ENABLE, ids);
        if (count > 0) {
            // 当前菜品处于起售中，不能被删除
            throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
        }
        List<Long> longs = setmealDishMapper.querySetmealByDishIds(ids);
        if (CollectionUtil.isNotEmpty(longs)) {
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }
        int result = dishMapper.deleteByIds(ids);
        if (result < 1) {
            return Result.error("删除失败");
        }
        dishFlavorMapper.deleteDishFlavorsByDishId(ids);
        List<Long> categoryIds = dishMapper.queryCategoryIdByIds(ids);
        List<String> list = categoryIds.stream().map(id -> "dish:" + id).collect(Collectors.toList());
        redisTemplate.delete(list);
        return Result.success("删除成功");
    }

    @Override
    public Result<DishDTO> getDishById(Long id) {
        if (Objects.isNull(id)) {
            return Result.error("请选择你要查询的菜品");
        }
        DishDTO dishDTO = dishMapper.queryDishById(id);
        if (Objects.isNull(dishDTO)) {
            return Result.error("暂无该菜品");
        }
        List<DishFlavor> dishFlavors = dishMapper.queryDishFlavorByDishId(id);
        dishDTO.setFlavors(dishFlavors);
        return Result.success(dishDTO);
    }

    @Override
    public Result<String> editDishStatus(Integer status, Long id) {
        if (Objects.isNull(id)) {
            return Result.error("请选择你要更改的菜品");
        }
        Dish dish = Dish.builder()
                .status(status)
                .id(id)
                .build();
        int result = dishMapper.updateDishStatus(dish);
        if (result < 1) {
            return Result.error("更改失败");
        }
        DishDTO dishDTO = dishMapper.queryDishById(id);
        redisTemplate.delete("dish:" + dishDTO.getCategoryId());
        return Result.success("更改成功");
    }

    @Override
    @Transactional
    public Result<String> editDish(DishDTO dishDTO) {
        Result<String> r = dishResult(dishDTO);
        if (!Objects.isNull(r)) {
            return r;
        }
        Dish dish = BeanUtil.copyProperties(dishDTO, Dish.class);
        DishDTO dishDto = dishMapper.queryDishById(dishDTO.getId());
        int result = dishMapper.updateDish(dish);
        if (result < 1) {
            return Result.error("更新菜品失败");
        }
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if (CollectionUtil.isNotEmpty(flavors)) {
            int row = dishFlavorMapper.updateDishFlavors(flavors);
            if (row < 1) {
                return Result.error("更新菜品失败");
            }
        }
        Long oldCategoryId = dishDto.getCategoryId();
        Long newCategoryId = dishDTO.getCategoryId();
        if (!Objects.equals(oldCategoryId, newCategoryId)) {
            List<String> categoryIds = Arrays.asList("dish:" + oldCategoryId, "dish:" + newCategoryId);
            redisTemplate.delete(categoryIds);
        } else {
            redisTemplate.delete("dish:" + newCategoryId);
        }
        return Result.success("更新菜品成功");
    }

    @Override
    public Result<List<DishVO>> list(Long categoryId) {
        if (Objects.isNull(categoryId)) {
            return Result.error("请选择你要查询的菜品");
        }
        String dishStr = (String) redisTemplate.opsForValue().get("dish:" + categoryId);
        if (StrUtil.isNotBlank(dishStr)) {
            List<DishVO> list = JSON.parseArray(dishStr, DishVO.class);
            if (CollectionUtil.isEmpty(list)) {
                return Result.success(Collections.emptyList());
            }
            redisTemplate.expire("dish:" + categoryId, 5L, TimeUnit.MINUTES);
            return Result.success(list);
        }
        Dish dish = new Dish();
        dish.setCategoryId(categoryId);
        dish.setStatus(StatusConstant.ENABLE);
        List<DishVO> list = dishMapper.list(dish);
        if (CollectionUtil.isEmpty(list)) {
            return Result.success(Collections.emptyList());
        }
        redisTemplate.opsForValue().set("dish:" + categoryId, JSON.toJSONString(list), 5L, TimeUnit.MINUTES);
        return Result.success(list);
    }

}
